"""Level classes."""

__author__ = 'Josh Oosterman'

import pygame

from potv import engine
from potv import geom
from potv.game import building
from potv.game import game
from potv.game import player
from potv.game import terrain


class Level(object):
  """Level manages all objects in non-menu screens."""

  def __init__(self, size):
    self.size = size
    self.views = [View(geom.Rect(0, 0, 800, 600), self)]
    self.objects = []

  def AddObject(self, obj):
    """Add an object to the level."""
    self.objects.append(obj)
    obj.level = self

  def Step(self):
    """Perform all frame update logic."""
    objects_stepable = [o for o in self.objects if hasattr(o, 'Step')]
    for object in objects_stepable:
      object.Step()

  def Draw(self, screen):
    """Render all objects in the level to the screen."""
    for view in self.views:
      #TODO(joosterman): Priority Queue or similar here.
      objects_drawable = [o for o in self.objects if hasattr(o, 'Draw')]
      depth_key = lambda x: x.depth if hasattr(x, 'depth') else 0
      objects_drawable.sort(key=depth_key, reverse=True)
      for object in objects_drawable:
        object.Draw(view)
      view.DrawToScreen(screen)


class View(object):
  """A view into a level."""

  def __init__(self, rect, level):
    self.level = level
    self.rect = rect
    self.world_location = geom.Vector(0, 0)
    self.surface = pygame.Surface((rect.width, rect.height))

  def Center(self, location):
    """Centers the view at a position in the level."""
    size = self.rect.Size()
    location = location - size / 2
    self.KeepInsideLevel()

  def KeepInsideLevel(self):
    size = self.rect.Size()
    location = self.world_location
    if location.x < 0:
      location.x = 0
    elif location.x + size.x > self.level.size.x:
      location.x = self.level.size.x - size.x
    if location.y < 0:
      location.y = 0
    elif location.y + size.y > self.level.size.y:
      location.y = self.level.size.y - size.y
    self.world_location = location

  def DrawToScreen(self, screen):
    """Draw the view surface to the screen surface."""
    screen.blit(self.surface, self.rect.ToPygameRect())
    self.surface.fill((0, 0, 0))

  def DrawImage(self, image, location):
    """Draw an image onto the view surface."""
    img = image.image
    location_relative = location - self.world_location
    img_rect = img.get_rect()
    img_rect.left = location_relative.x - image.origin.x
    img_rect.top = location_relative.y - image.origin.y
    self.surface.blit(img, img_rect)
    if game.DEBUG:
      pygame.gfxdraw.hline(
        self.surface,
        location_relative.x - 5,
        location_relative.x + 5,
        location_relative.y,
        pygame.Color('white'))
      pygame.gfxdraw.vline(
        self.surface,
        location_relative.x,
        location_relative.y - 5,
        location_relative.y + 5,
        pygame.Color('white'))
